<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2017/9/25
 * Time: 11:58
 */
function pre($data)
{
    echo '<pre>';
    print_r($data);
    echo '</pre>';
}

//php中实现获取随机数组列表的自定义函数
function create_random_ids($min, $max, $limited)
{
    $base_array = range($min, $max);

    $_temp_key = array_rand($base_array, min(count($base_array), $limited + 10));
    //array_rand() 函数返回数组中的随机键名，或者如果您规定函数返回不只一个键名，则返回包含随机键名的数组。
    //拼接
    $ids = array();
    for ($x = 0; $x < count($_temp_key); $x++) {
        $ids[] = $base_array[$_temp_key[$x]];
    }
    return $ids;
}

//mt_rand 如果没有提供可选参数 min 和 max，mt_rand() 返回 0 到 RAND_MAX 之间的伪随机数。例如想要 5 到 15（包括 5 和 15）之间的随机数，用 mt_rand(5, 15)。

//实现在数据库百万条数据中随机获取20条记录的方法
$num = 1000000; //先统计统计数据库多少条记录（这个做个数据缓存，如1小时重新统计一次），
//2.根据总条数，随机1次，1次性取出20条记录（当然这个就相当于分页了，要求不高的话，这个最快，我用的就是这个)
for ($i = 1; $i <= 20; $i++) {
    $offset = mt_rand(1, $num);
    //控制重复对比的，请自行实现
    //数据库取数据的，请自行实现
    $sql = "select * from table_name limit $offset,1";
    return $sql;
}
function arraySort($arr, $keys, $type = 'asc')
{
    $keys_value = $new_array = array();
    foreach ($arr as $index => $item) {
        $keys_value[$index] = $item[$keys];
    }
    $type == 'asc' ? asort($keys_value) : arsort($keys_value);
    reset($keys_value);
    foreach ($keys_value as $index => $item) {
        $new_array[$index] = $arr[''];
    }
}

//获取连个数组之间的差集

function array_diff_two(array $arr, array $array)
{
    $res_arr = array_merge(array_diff($arr, $array), array_diff($array, $arr));  //array_diff 比较两个数组的键值，并返回差集： 函数返回两个数组的差集数组。该数组包括了所有在被比较的数组中，但是不在任何其他参数数组中的键值。
    return $res_arr;
}

//自定义去除数组中重复的的键值
//有一个比较好而且更快的函数array_flip()来替代使用array_unique()函数来创建唯一的数组。这个魔法般的函数会交换数组里面每一个元素的键和值，因为键值必须唯一，因此，你会得到跟array_unique()函数一样的结果。
function _array_unique(array $array)
{
    $array = is_array($array) ? $array : (array)$array;
    $array = array_flip($array);  //翻转数组，你将会得到唯一键值的数组
    $array = array_flip($array);
//    array_merge()如果只给了一个数组并且该数组是数字索引的，则键名会以连续方式重新索引。
    $new_array = array_merge($array);//添加array_flip之后的函数，将会对数组的键值排序并且让它们恢复到正常的序列，如：0,1,2,3…
    return $new_array;
}

if (!function_exists('array_fill')) {
    function array_fill($iStart, $iLen, $vValue)
    {
        $aResult = array();
        for ($iCount = $iStart; $iCount < $iLen + $iStart; $iCount++) {
            $aResult[$iCount] = $vValue;
        }
        return $aResult;
    }
}
//检测url地址是否合法
function check_url($url)
{

    if (preg_match('/^(http|https|ftp)://([A-Z0-9][A-Z0-9_-]*(?:.[A-Z0-9][A-Z0-9_-]*)+):?(d+)?/?/i', $url)) {
        return true;
    } else {
        return false;
    }
//    $pattern_1 = "/^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i";
//    $pattern_2 = "/^(www)((\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i";
//    if(preg_match($pattern_1, $url) || preg_match($pattern_2, $url)){
//        return true;
//    } else{
//        return false;
//    }
}

//PHP用正则匹配获取URL中的信息 PHP的官网上看到的parse_url()函数的替代方案
if (!function_exists('parse_url')) {
    function _parse_url($url)
    {
        $search = '~^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?~i';
        $url = trim($url);
        preg_match_all($search, $url, $matches);
        return $matches;
    }
}
if (function_exists('file_get_contents')) {
    function _file_get_contents($url)
    {
        if (check_url($url)) {
            $html = file_get_contents($url);
            return $html;
        }
    }
}

function upload_down_file($load_file_path, $local_file_name, $down_file_name, $is_limit = false, $download_file_rate = 100)
{
    $rootPath = $_SERVER['DOCUMENT_ROOT'];
    $load_file_path = isset($load_file_path) ? $load_file_path : $rootPath . '/UploadDown/';
    $load_file = isset($local_file_name) ? $local_file_name : 'com.dingapp.andriod.shundao_1.1.0_4.apk';
    $down_file_name = isset($down_file_name) ? $down_file_name : time() . '.apk';
    $local_file_size = filesize($load_file_path . $local_file_name);
    if (file_exists($load_file_path . $local_file_name) && is_file($load_file_path . $local_file_name)) {
        header('Cache-control:private');
        header('Content-Type: application/octet-stream');
        header("Accept-Ranges: bytes");
        header('Content-Length: ' . $local_file_size);
        header('Content-Disposition:attachment; filename=' . $down_file_name);
        flush();
        $file_fp = fopen($load_file_path . $local_file_name, 'r');
        if ($is_limit === true) {
            $already_file_size = 0;
            while (!feof($file_fp) && $already_file_size < $local_file_size) {
                print  fread($file_fp, round($download_file_rate * 1024));
                $already_file_size += $download_file_rate * 1024;

            }
        } else {
            print fread($file_fp, $local_file_size);
        }
        fclose($file_fp);
    } else {
        return false;
    }

}

/**
 * @param $load_file_path
 * @return bool
 * @User: yfl
 * @Time: 2017年9月22日 11:42:29
 * @description: 检测目录是否存在没有则创建
 */
function is_make_dir($load_file_path)
{
    $rootPath = $_SERVER['DOCUMENT_ROOT'];
    if (!file_exists($rootPath . $load_file_path)) {
        return mkdir($rootPath . $load_file_path, 0777);
    }

}

/**
 * @param $xml
 * @return mixed
 * @User: yfl
 * @Time: 2017年9月26日 15:52:54
 * @description: 将xml转为array
 */
function xmlToArray($xml)
{

    $xml = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
    return json_decode(json_encode($xml), true);
}

/**
 * 获取英文月份
 */
function getEnglishMonth($key)
{
    $month = array(
        "01" => "Jan",
        "02" => "Feb",
        "03" => "Mar",
        "04" => "Apr",
        "05" => "May",
        "06" => "Jun",
        "07" => "Jul",
        "08" => "Aug",
        "09" => "Sep",
        "10" => "Oct",
        "11" => "Nov",
        "12" => "Dec");
    return $month[$key];
}

/**
 * @return string
 * @User: yfl
 * @Time: 2017年9月22日 13:52:42
 * @description:判断客户端是IOS还是Android
 */
function check_user_agent()
{
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'iPhone') || strpos($_SERVER['HTTP_USER_AGENT'], 'iPad') || strpos($_SERVER['HTTP_USER_AGENT'], "iPod")) {
        return 'IOS';
    } else if (strpos($_SERVER['HTTP_USER_AGENT'], 'Android')) {
        return 'Android';
    } else {
        return 'other';
    }
}


/**
 * @param $filename
 * @return mixed|string
 * @User: yfl
 * @Time:2017年10月13日 16:45:03
 * @description: 获取请求的  MIME_TYPE类型
 */
function _mime_content_type($filename)
{

    $mime_types = array(

        'txt' => 'text/plain',
        'htm' => 'text/html',
        'html' => 'text/html',
        'php' => 'text/html',
        'css' => 'text/css',
        'js' => 'application/javascript',
        'json' => 'application/json',
        'xml' => 'application/xml',
        'swf' => 'application/x-shockwave-flash',
        'flv' => 'video/x-flv',

        // images
        'png' => 'image/png',
        'jpe' => 'image/jpeg',
        'jpeg' => 'image/jpeg',
        'jpg' => 'image/jpeg',
        'gif' => 'image/gif',
        'bmp' => 'image/bmp',
        'ico' => 'image/vnd.microsoft.icon',
        'tiff' => 'image/tiff',
        'tif' => 'image/tiff',
        'svg' => 'image/svg+xml',
        'svgz' => 'image/svg+xml',

        // archives
        'zip' => 'application/zip',
        'rar' => 'application/x-rar-compressed',
        'exe' => 'application/x-msdownload',
        'msi' => 'application/x-msdownload',
        'cab' => 'application/vnd.ms-cab-compressed',

        // audio/video
        'mp3' => 'audio/mpeg',
        'qt' => 'video/quicktime',
        'mov' => 'video/quicktime',

        // adobe
        'pdf' => 'application/pdf',
        'psd' => 'image/vnd.adobe.photoshop',
        'ai' => 'application/postscript',
        'eps' => 'application/postscript',
        'ps' => 'application/postscript',

        // ms office
        'doc' => 'application/msword',
        'rtf' => 'application/rtf',
        'xls' => 'application/vnd.ms-excel',
        'ppt' => 'application/vnd.ms-powerpoint',

        // open office
        'odt' => 'application/vnd.oasis.opendocument.text',
        'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
    );
    $arr = explode('.', $filename);
    $ext = strtolower(array_pop($arr));
    if (array_key_exists($ext, $mime_types)) {
        return $mime_types[$ext];
    } elseif (function_exists('finfo_open')) {
        $finfo = finfo_open(FILEINFO_MIME);
        $mimetype = finfo_file($finfo, $filename);
        finfo_close($finfo);
        return $mimetype;
    } else {
        return 'application/octet-stream';
    }

}

/**
 * @param ReflectionClass $reflectionClass
 * @return array|bool
 * @User: yfl
 * @Time: 2017年10月13日 17:04:03
 * @description: 通过反射获得类源码
 */
function getSource(ReflectionClass $reflectionClass)
{
    $path = $reflectionClass->getFileName();#获取脚本文件的文件名和绝对路径
    $fpArr = file($path); //file() 函数 获取文件的内容 把整个文件读入一个数组中 数组的每一个元素保存一行的内容。
    $start = $reflectionClass->getStartLine();
    $end = $reflectionClass->getEndLine();
    $array = array_slice($fpArr, $start - 1, $end - $start + 1);#拼装类源码
    return $array;
}

/**
 * 本文实例讲述了PHP递归实现文件夹的复制、删除、查看大小操作。分享给大家供大家参考，具体如下：
 * PHP虽然提供了 filesize、copy、unlink 等文件操作的函数，但是没有提供
 * dirsize、copydir、rmdirs 等文件夹操作的函数（rmdir也只能删除空目录）。
 * 所以只能手动编写这些函数，主要的技巧是通过递归将问题逐层分解，直到分解成可以直接解决的最小子问题。
 */
/**
 * @param $path：文件路径
 * @return int
 * @User: yfl
 * @Time: 2017年10月18日 09:06:53
 * @description: 查看文件的大小
 */
function dir_size($path = null)
{
//    $dir=dirname(__DIR__).'\study';
//    $path=isset($path)?$path:$dir;
    $size = 0;
    $handle = opendir($path);
    while (($item = readdir($handle)) !== false) {  //判断递归结束的位置
        if ($item == '.' || $item == '..') continue;
        $str_path = $path . '/' . $item;
        if (is_file($str_path)) $size += filesize($str_path);
        if (is_dir($str_path)) $size += dir_size($str_path);
    }
    closedir($handle);
    return $size;
}

/**
 * 上下两个函数的比较和理解
 * 迭代和递归都具有初始化变量 、 判断结束条件 、执行实际操作、产生新变量这四个步骤
 * 比如 初始化变量这一步骤 在迭代中是位于函数的开始部分，而在递归中是指其他函数的传递参数的这一过程
 * 判断结束条件这一步骤 在迭代中用于判断循环是否继续 在递归中用于判断递归的结束位置
 * 执行实际操作在递归和迭代中都是函数的核心部分位于产生新变量步骤之前
 * 产生新变量在迭代中是迭代是否继续的条件 在递归中是下一次递归的基础 由于产生了心变量才使得递归活迭代继续进行
 */
/**
 * @param null $path
 * @return int
 * @User: yfl
 * @Time: 2017年10月18日 16:57:23
 * @description:迭代统计一个文件的大小 和上边的递归统计的方法差别几乎可以忽略不计
 * 迭代的思路是让计算机对一组指令进行重复执行，在每次执行这组指令时，都从变量的原值推出其它的新值……重复这一过程直到达到结束条件或没有新值产生。
 * @from http://www.jb51.net/article/120914.htm
 */
function iteration_dir_size($path = null)
{
//    $dir=dirname(__DIR__).'\study';
//    $path=isset($path)?$path:$dir;
    $size = 0;
    $stack = array(); //初始的条件
    if (file_exists($path)) {
        $path = realpath($path) . '/';
        array_push($stack, '');
    } else {
        return -1;
    }
    //迭代的条件
    while (count($stack) !== 0) { //判断循环是否继续
        $dir = array_pop($stack);
        $handle = opendir($path . $dir);
        //执行过程
        while (($item = readdir($handle)) !== false) {
            if ($item == '.' || $item == '..') continue;
            $_path = $path . $dir . $item;
            if (is_file($_path)) {
                $size += filesize($_path);
            }
            if (is_dir($_path)) {
                array_push($stack, $dir . $item . '/');
            }
        }
        closedir($handle);
    }
    return $size;
}

/**
 * 复制文件夹
 * 文件是可以复制的，文件夹是不能复制的（但可以创建），如果要达到复制文件夹的效果，就需要生成一个和原始文件夹相同目录结构的新文件夹，
 * 然后将文件按照原目录结构复制到新文件夹。按照递归的思想，不用一开始就生成完整的目录结构，只需要遍历当前目录，发现文件夹不存在再创建即可，
 * 然后再将文件复制到对应的文件夹。
 */
/**
 * @param $source : 要copy的文件目录
 * @param $copy_to_path :copy到哪里目录
 * @User: yfl
 * @Time: 2017年10月18日 09:42:22
 * @description: 递归复制文件夹和文件
 */
function copy_dir($source, $copy_to_path)
{
    if (!file_exists($copy_to_path)) mkdir($copy_to_path);
    $handle = opendir($source);
    while (($item = readdir($handle)) !== false) {
        if ($item == '.' || $item == '..') continue;
        $_source = $source . '/' . $item;
        $_copy_to_path = $copy_to_path . '/' . $item;
        if (is_file($_source)) copy($_source, $_copy_to_path);
        if (is_dir($_source)) copy_dir($_source, $_copy_to_path);
    }
    closedir($handle);
}

/**
 * 删除文件夹rmdir 只能删除空文件夹，而 unlink 可以删除文件。于是删除文件夹的思路就有了，先通过 unlink 删除目录下的所有文件，
 * 再通过 rmdir 删除剩下的空文件夹。使用递归处理的逻辑是，找到当前目录下所有文件和文件夹，删除其中的所有文件，
 * 再遍历下一层目录删除所有文件……直至最后一层目录，此时整个文件夹已经没有文件了（但是文件夹还在），
 * 此时递归开始返回，每向上返回一层就删除这一层的所有空目录，当返回到最顶层的时候，递归就结束了，同时所有的文件和目录也都删除了。
 */
/**
 * @param $path
 * @return bool
 * @User: yfl
 * @Time: 2017年10月18日 14:32:06
 * @description: 清空文件夹
 */
function remove_dir($path)
{
    if (!file_exists($path)) return false;
    $handle = opendir($path);
    while (($item = readdir($handle)) !== false) {
        if ($item == '.' || $item == '..') continue;
        $_path = $path . '/' . $item;
        if (is_file($_path)) @unlink($_path);
        if (is_dir($_path)) remove_dir($_path);
    }
    closedir($handle);
    return rmdir($path);
}


/**
 * rename 是 PHP Filesystem 函数中的一个特例，它既可以重命名文件，也可以重命名文件夹。
 * 如果你为重命名文件传入不同的路径，它又成了剪切函数，堪称文件函数中小而美的典范。
 */
/**
 * @param $old_name :必需。规定要重命名的文件或目录。
 * @param $new_name :必需。规定文件或目录的新名称。
 * @param array $context 可选。规定文件句柄的环境。
 * @return string
 * @User: yfl
 * @Time:2017年10月18日 11:58:30
 * @description: 重命名文件或者剪切文件
 */
function rename_or_shear_file($old_name, $new_name, $context = array())
{
//    if (!empty($context) && is_array($context)) {
//             $opts=stream_context_create($context);
//    }
    if (!file_exists($old_name)) return false;
    if (dirname($old_name) == dirname($new_name)) {
        rename($old_name, $new_name);
        return 'copy'; // 复制
    } else {
        rename($old_name, $new_name);
        return 'share'; //剪切
    }
}

/**
 * @param $path
 * @User: yfl
 * @Time: 2017年10月18日 11:56:44
 * @description: 获取 $PATH 中不含磁盘符号的目录
 */
function get_path($path)
{
//strrchr 该函数返回 haystack 字符串中的一部分，这部分以 needle 的最后出现位置开始，直到 haystack 末尾。
    $dir = substr(strrchr($path, ":"), 1);
    return $dir;
}


/**
 * @param $func
 * @return int
 * @User: yfl
 * @Time:2017年10月18日 15:06:46
 * @description: 函数执行毫秒数
 */
function exec_time($func)
{
    $start = explode(' ', microtime());
    $func();
    // 执行耗时操作
    $end = explode(' ', microtime());
    $sec_time = floatval($end[0]) - floatval($start[0]);
    $mic_time = floatval($end[1]) - floatval($start[1]);
    return intval(($sec_time + $mic_time) * 1000);
}

/**
 * @param $url
 * @return mixed $match_arr[0] img标签  $match_arr[1] img标签的URl地址
 * @User: yfl
 * @Time: 2017年10月20日 15:07:24
 * @description:PHP提取字符串中的图片地址[正则表达式]
 */
function get_html_img($url)
{

    $html_str = file_get_contents($url);
    $pattern = "/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.png]))[\'|\"].*?[\/]?>/";
    /*    $pattern="/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg]))[\'|\"].*?[\/]?>/";*/
    preg_match_all($pattern, $html_str, $match_arr);
    return $match_arr;
}

/**
 *
 */
/**
 * @param $str :例子：$content = "Current date and time is ".date("Y-m-d h:i a").", we are learning PHP together.";
 * @User: yfl
 * @Time: 2017年10月20日 16:00:19
 * @description: 获得字符串的日期时间
 */
function get_str_time($str)
{
    if (preg_match("/\d{4}-\d{2}-\d{2} \d{2}:\d{2} [ap]m/", $str, $m)) {
        echo "匹配的时间是：" . $m[0] . "\n";
    }
}

/**
 * @param $date
 * @param $symbol
 * @return string
 * @User: yfl
 * @Time: 2017年10月20日 16:12:36
 * @description: 将日期正则分开     例子：handle_time_date('08/30/2006','-');  结果2006-08-30
 */
function handle_time_date($date, $symbol)
{
    list($month, $day, $year) = preg_split('/[\/.-]/', $date);

    return $year . $symbol . $month . $symbol . $day;
}

/**
 * @param $str
 * @param $preg
 * @return array
 * @User: yfl
 * @Time: 2017年10月20日 16:18:31
 * @description: 用正则切割字符串 转化为数组
 */
function preg_handle_str($str, $preg = '')
{
//    //使用逗号或空格(包含" ", \r, \t, \n, \f)分隔短语
//    $keywords = preg_split("/[\s,]+/", "hypertext language, programming");
    $preg = empty($preg) ? "/[\s,]/" : $preg;
    $arr_res = preg_split($preg, $str);
    return $arr_res;
}

/**
 * @return array
 * @User: yfl
 * @Time: 2017年10月20日 16:25:36
 * @description: 正则计算一个字符串的单词数量
 */
function preg_get_str_count()
{
    $seek = array();
    $text = "I have a dream that one day I can make it. So just do it, nothing is impossible!";
   //将字符串按空白，标点符号拆分（每个标点后也可能跟有空格）
    $words_arr = preg_split("/[.,;!\s']\s*/", $text);
    return $words_arr;
}

/**
 * @param $string
 * @param $patterns
 * @param $replacements
 * @return mixed
 * @User: yfl
 * @Time:2017年10月20日 16:30:55
 * @description: 正则使用数组替换字符串的数据
 */
function preg_replace_arr($string,$patterns,$replacements){

//    //字符串
//    $string = "Name: {Name}<br>\nEmail: {Email}<br>\nAddress: {Address}<br>\n";
////模式
//    $patterns =array(
//        "/{Address}/",
//        "/{Name}/",
//        "/{Email}/"
//    );
////替换字串
//    $replacements = array (
//        "No.5, Wilson St., New York, U.S.A",
//        "Thomas Ching",
//        "tom@emailaddress.com",
//    );
//输出模式替换结果
   return preg_replace($patterns, $replacements, $string);
}

/**
 * @param $text
 * @return mixed
 * @User: yfl
 * @Time: 2017年10月20日 16:38:19
 * @description: 将文本中的url链接 放到<a>标签里
 * $str = "这是一个包含多个URL链接地址的多行文字。欢迎访问http://www.jb51.net";
   echo url2html($str);
 */
function url2html($text)
{
//匹配一个URL，直到出现空白为止
    preg_match_all("/http:\/\/?[^\s]+/i", $text, $links);
//设置页面显示URL地址的长度
    $max_size = 40;
    foreach($links[0] as $link_url)
    {
//计算URL的长度。如果超过$max_size的设置，则缩短。
        $len = strlen($link_url);
        if($len > $max_size)
        {
            $link_text = substr($link_url, 0, $max_size)."...";
        } else {
            $link_text = $link_url;
        }
//生成HTML文字
        $text = str_replace($link_url,"<a href='$link_url'>$link_text</a>",$text);
    }
    return $text;
}